package controller

import (
	"equantum/common"
	"equantum/dto"
	"equantum/model"
	"equantum/response"
	"equantum/util"
	"fmt"
	"log"
	"math/rand"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/jinzhu/gorm"
	"golang.org/x/crypto/bcrypt"
)

func SendVCode(ctx *gin.Context) {
	DB := common.GetDB()
	RDB := common.GetRDB()

	// 获取参数
	// var requestUser = model.User{}
	// ctx.Bind(&requestUser)
	// email := requestUser.Email
	email := ctx.PostForm("email")

	// 数据验证
	if len(email) == 0 {
		response.Response(ctx, http.StatusUnprocessableEntity, 422, nil, "邮箱不能为空")
		return
	}
	if isEmailExist(DB, email) {
		response.Response(ctx, http.StatusUnprocessableEntity, 422, nil, "用户已经存在")
		return
	}

	// 查看是否已生成验证码
	vcode, err := RDB.Get(ctx, email).Result()
	if vcode == "" {
		// 生成6位随机验证码
		vcode = genVCode()

		// 验证码存入redis，有效期30分钟
		err = RDB.Set(ctx, email, vcode, 30*time.Minute).Err()
		if err != nil {
			response.Response(ctx, http.StatusInternalServerError, 500, nil, "系统异常")
			log.Printf("vcode insertion error : %v", err)
			return
		}
	}

	// 发送验证码到用户邮箱
	err = util.SendVcodeMail(email, vcode)
	if err != nil {
		response.Response(ctx, http.StatusInternalServerError, 500, nil, "系统异常")
		log.Printf("err sending email: %v", err)
		return
	}

	// 返回验证码发送结果
	response.Success(ctx, nil, "验证码发送成功")
}

func Register(ctx *gin.Context) {
	DB := common.GetDB()
	RDB := common.GetRDB()

	// 获取参数
	name := ctx.PostForm("name")
	email := ctx.PostForm("email")
	vcode := ctx.PostForm("vcode")
	password := ctx.PostForm("password")

	// 数据验证
	if len(name) == 0 || len(email) == 0 || len(vcode) == 0 || len(password) == 0 {
		response.Response(ctx, http.StatusUnprocessableEntity, 422, nil, "必填字段不能为空")
		return
	}
	// 判断邮箱是否存在
	if isEmailExist(DB, email) {
		response.Response(ctx, http.StatusUnprocessableEntity, 422, nil, "用户已经存在")
		return
	}

	// 判断验证码是否正确
	vcodeRDB, err := RDB.Get(ctx, email).Result()
	if vcode != vcodeRDB {
		response.Response(ctx, http.StatusBadRequest, 400, nil, "验证码错误")
		return
	}

	// 删除使用过的验证码
	err = RDB.Del(ctx, email).Err()
	if err != nil {
		response.Response(ctx, http.StatusInternalServerError, 500, nil, "系统异常")
		return
	}

	// 密码加密
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		response.Response(ctx, http.StatusInternalServerError, 500, nil, "系统异常")
		return
	}

	// 创建用户
	newUser := model.User{
		Name:     name,
		Email:    email,
		Password: string(hashedPassword),
	}
	DB.Create(&newUser)

	// 发放token
	token, err := common.ReleaseToken(newUser)
	if err != nil {
		response.Response(ctx, http.StatusInternalServerError, 500, nil, "系统异常")
		log.Printf("token generate error : %v", err)
		return
	}

	// 返回注册登录结果
	response.Success(ctx, gin.H{"token": token}, "注册成功")
}

func Login(ctx *gin.Context) {
	DB := common.GetDB()

	// 获取参数
	email := ctx.PostForm("email")
	password := ctx.PostForm("password")

	// 数据验证
	if len(email) == 0 {
		response.Response(ctx, http.StatusUnprocessableEntity, 422, nil, "邮箱不能为空")
		return
	}

	// 判断用户是否存在
	var user model.User
	DB.Where("email = ?", email).First(&user)
	if user.ID == 0 {
		response.Response(ctx, http.StatusUnprocessableEntity, 422, nil, "用户名或密码错误")
		return
	}

	// 判断密码是否正确
	if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
		response.Response(ctx, http.StatusBadRequest, 400, nil, "用户名或密码错误")
		return
	}

	// 发放token
	token, err := common.ReleaseToken(user)
	if err != nil {
		response.Response(ctx, http.StatusInternalServerError, 500, nil, "系统异常")
		log.Printf("token generate error : %v", err)
		return
	}

	// 返回登录结果
	response.Success(ctx, gin.H{"token": token}, "登录成功")
}

func Info(ctx *gin.Context) {
	user, _ := ctx.Get("user")

	response.Success(ctx, gin.H{"user": dto.ToUserDto(user.(model.User))}, "")
}

// utils

func genVCode() string {
	rand.Seed(time.Now().Unix()) //设置随机种子
	vcode := fmt.Sprintf("%6v", rand.Intn(600000))
	return vcode
}

func isTelephoneExist(db *gorm.DB, telephone string) bool {
	var user model.User
	db.Where("telephone = ?", telephone).First(&user)
	if user.ID != 0 {
		return true
	}
	return false
}

func isEmailExist(db *gorm.DB, email string) bool {
	var user model.User
	db.Where("email = ?", email).First(&user)
	if user.ID != 0 {
		return true
	}
	return false
}
